# Copyright (c) 2009, Gryanko Alexander (gryanko@corp.liveinternet.ru)
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the LiveInternet nor the
#       names of its contributors may be used to endorse or promote products
#       derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY Gryanko Alexander ''AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import re

from genshi.builder import tag
from genshi.template import MarkupTemplate

from trac.core import *
from trac.web import IRequestHandler
from trac.web.chrome import INavigationContributor, ITemplateProvider, add_stylesheet
from trac.perm import IPermissionRequestor, PermissionError

    
class ServerConf(Component):
    implements(INavigationContributor, IRequestHandler, ITemplateProvider, IPermissionRequestor)
    
    # IPermissionRequestor methods
    def get_permission_actions(self):
        return ['HOSTS_VIEW', 'HOSTS_MODIFY']

    # ITemplateProvider methods
    def get_htdocs_dirs(self):
        from pkg_resources import resource_filename
        return [('hw', resource_filename(__name__, 'htdocs'))]

    def get_templates_dirs(self):
        from pkg_resources import resource_filename
        return [resource_filename(__name__, 'templates')]

    # IRequestHandler methods
    
    def match_request(self, req):
            if re.match('/hosts/?$', req.path_info) is not None:
                return True
            match = re.match('/hosts/([a-zA-Z_-]+)$', req.path_info)
            if match:
                req.args['action'] = match.group(1)
                return True

    def process_request(self, req):
        if 'action' in req.args:
            return self._process_hosts_action(req)
        return self._process_hosts_list(req)
    
    def _process_hosts_action(self, req):
        if req.args['action'] == "add_form":
            return self._form_add(req)
        if req.args['action'] == "add":
            return self._add_data(req)
        if req.args['action'] == 'delete':
            return self._delete_data(req)
        if req.args['action'] == 'edit_form':
            return self._edit_form(req)
        if req.args['action'] == 'edit':
            return self._edit(req)
        if req.args['action'] == "sort_nd":
            return self._sort(req, 'name', True)
        if req.args['action'] == "sort_nu":
            return self._sort(req, 'name', False)
        if req.args['action'] == "sort_md":
            return self._sort(req, 'mark', True)
        if req.args['action'] == "sort_mu":
            return self._sort(req, 'mark', False)
        if req.args['action'] == "sort_id":
            return self._sort(req, 'ip', True)
        if req.args['action'] == "sort_iu":
            return self._sort(req, 'ip', False)
    
    def _process_hosts_list(self, req):
        req.perm.require('HOSTS_VIEW')
        
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute('''SELECT DISTINCT 
                        `id`, 
                        `name`, 
                        `mark`, 
                        `description`, 
                        `cpu`, 
                        `ram`, 
                        `disk`, 
                        `os`, 
                        `ip`, 
                        `rack_unit`, 
                        `kvm`,
                        `kvm_name` 
                        FROM `hosts` ORDER BY `name` ASC''')
        
        add_stylesheet(req, 'hw/css/hosts.css')
        return ('hosts.html', {'lists': cursor.fetchall(), 'url' : self.env.config.get('hosts', 'url') }, None)
    
    # INavigationContributor method
    
    def get_navigation_items(self, req):
        if 'HOSTS_VIEW' in req.perm:
            yield('mainnav', 'hosts', 
              tag.a("Hosts", href=req.href.hosts(), 
                    accesskey=10))
    
    def get_active_navigation_item(self, req):
        if 'HOSTS_VIEW' in req.perm:
            return 'hosts'
        
    def _form_add(self, req):
        req.perm.require('HOSTS_MODIFY')
        
        return ('add_form.html', {}, None)
    
    def _add_data(self, req):
        req.perm.require('HOSTS_MODIFY')
        
        if req.method == "POST":
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            try:
                cursor.execute('''INSERT INTO `hosts`(
                `name`, `mark`, `description`, `cpu`, `ram`, `disk`, `os`, `ip`, `rack_unit`, `kvm`, `kvm_name`) 
                VALUES(%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s);''', 
                [req.args['name'], req.args['mark'], req.args['description'], req.args['cpu'], req.args['ram'], req.args['disk'], req.args['os'], req.args['ip'], req.args['rack_unit'], req.args['kvm'], req.args['kvm_name']]);
            except db.Error, e:
                return ('message_error.html', {'error' : e}, None)
            
            return ('message.html', {'data' : 'Host has been added'}, None)
        else:
            return ('message_error.html', {'error' : 'Request error'}, None)
    
    def _delete_data(self, req):
        req.perm.require('HOSTS_MODIFY')
        
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        
        for obj in req.args['delete']:
            try:
                cursor.execute('''DELETE FROM `hosts` 
                            WHERE `id` = %d; '''  % (int(obj)))
            except db.Error, e:
                return ('message_error.html', {'error' : e}, None)
        
        return ('message.html', {'data': 'Host has been deleted'}, None)
    
    def _edit_form(self, req):
        req.perm.require('HOSTS_MODIFY')
        
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        
        cursor.execute("SELECT DISTINCT " 
                        "`name`, "
                        "`mark`, "
                        "`description`, "
                        "`cpu`, "
                        "`ram`, "
                        "`disk`, "
                        "`os`, "
                        "`ip`, "
                        "`rack_unit`, "
                        "`kvm`, "
                        "`kvm_name` "
                        "FROM `hosts` "
                        "WHERE `id` = %s", req.args['id'])
        
        return ('edit_form.html', {'data' : cursor.fetchone(), 'id' : req.args['id']}, None)
    
    def _edit(self, req):
        req.perm.require('HOSTS_MODIFY')
        
        if req.method == "POST":
            db = self.env.get_db_cnx()
            cursor = db.cursor()
            try:
                cursor.execute('''UPDATE `hosts` SET 
                `name` = %s, 
                `mark` = %s, 
                `description` = %s, 
                `cpu` = %s, 
                `ram` = %s, 
                `disk` = %s, 
                `os` = %s, 
                `ip` = %s, 
                `rack_unit` = %s, 
                `kvm` = %s,
                `kvm_name` = %s
                WHERE `id` = %s;''', 
                [req.args['name'], req.args['mark'], req.args['description'], req.args['cpu'], req.args['ram'], req.args['disk'], req.args['os'], req.args['ip'], req.args['rack_unit'], req.args['kvm'], req.args['kvm_name'], req.args['id']]);
            except db.Error, e:
                return ('message_error.html', {'error' : e}, None)
            
            return ('message.html', {'data' : 'Host has been updated'}, None)
        else:
            return ('message_error.html', {'error' : 'Request error'}, None)
    
    def _sort(self, req, table, order):
        req.perm.require('HOSTS_VIEW')
        if order:
            query = '''SELECT DISTINCT  
                        `id`, 
                        `name`, 
                        `mark`, 
                        `description`, 
                        `cpu`, 
                        `ram`, 
                        `disk`, 
                        `os`, 
                        `ip`, 
                        `rack_unit`, 
                        `kvm`, 
                        `kvm_name`
                        FROM `hosts` ORDER BY `%s` DESC''' % (table)
        else:
            query = '''SELECT DISTINCT  
                        `id`, 
                        `name`, 
                        `mark`, 
                        `description`, 
                        `cpu`, 
                        `ram`, 
                        `disk`, 
                        `os`, 
                        `ip`, 
                        `rack_unit`, 
                        `kvm`, 
                        `kvm_name`
                        FROM `hosts` ORDER BY `%s` ASC''' % (table)  
        db = self.env.get_db_cnx()
        cursor = db.cursor()
        cursor.execute(query)
        
        add_stylesheet(req, 'hw/css/hosts.css')
        return ('hosts.html', {'lists': cursor.fetchall(), 'url' : self.env.config.get('hosts', 'url')}, None) 